import java.io.*;
import java.net.*;

/**
 * @author Hao Wu
 * 
 *         standalone Java http server
 * 
 */
public class Service {

	private int port;
	private int i;

	public Service(int port) {
		this.i = 1;
		this.port = port;
	}

	public void start() {
		ServerSocket server = null;
		Socket client = null;
		try {
			server = new ServerSocket(port);
			System.out.println("Web Server is listening on port "
					+ server.getLocalPort());
			for (;;) {
				client = server.accept();
				new ConnectionThread(client, i).start();
				i++;
			}
		} catch (Exception e) {
			System.out.println(e);
		}
	}

}

/**
 * @author howellwoo
 * 
 */
class ConnectionThread extends Thread {
	Socket client;

	int counter;

	public ConnectionThread(Socket cl, int c) {
		client = cl;
		counter = c;
	}

	public void run() {
		try {
			String destIP = client.getInetAddress().toString();
			int destport = client.getPort();
			System.out.println("Connection " + counter + ":connected to "
					+ destIP + " on port " + destport + ".");
			PrintStream outstream = new PrintStream(client.getOutputStream());
			DataInputStream instream = new DataInputStream(
					client.getInputStream());
			String inline = instream.readLine(); // read request
			System.out.println("Received:" + inline);
			if (getrequest(inline)) { // if it is a GET
				String filename = getfilename(inline);
				File file = new File(filename);
				int state = getState(filename); // Get state number

				// if login-ed we jump to our Key
				if (state == 0) {
					System.out.println("JUMPED" + " requested.");

					String outp = Util.genToKey();
					int len = outp.length();
					String o = "HTTP/1.0 200 OK\r\n" + "Content-Length: " + len
							+ "\r\n" + "MIME_version:1.0\r\n"
							+ "Content_Type:text/html; charset=utf-8 \r\n\r\n"
							+ outp + "\r\n";
					outstream.println(o);

					outstream.flush();
					// outstream.close();
				} else {
					if (state == 1) {// if is Key location
						String comm = this.getCommand(filename); // get command
						TextIO.putln(comm);

						// parse the command, and exec the command
						if (comm.equals("null") == false) {
	// if there is a command to run, send the jump html again so user won't see anything in the url, and safely refresh 
							String cod = "";
							String[] tmp = comm.split("###");
							if (tmp[0].equals("open")) {
								TextIO.putln(tmp[1]);
								for (CuratorPS x : Entry.curatorList) {
									if (x.getName().equals(tmp[1]))
										x.start();
								}

							}
							if (tmp[0].equals("close")) {
								cod = "kill " + tmp[1];
								Util.exec(cod);
							}

							System.out.println("LOGIN-JUMPED" + " requested.");

							String outp = Util.genToKey();
							int len = outp.length();
							String o = "HTTP/1.0 200 OK\r\n"
									+ "Content-Length: "
									+ len
									+ "\r\n"
									+ "MIME_version:1.0\r\n"
									+ "Content_Type:text/html; charset=utf-8 \r\n\r\n"
									+ outp + "\r\n";
							outstream.println(o);

							outstream.flush();

						} else {
					// if no command find.
							System.out.println("Loged in" + " requested.");
							String outp = Util.genHTML();

							int len = outp.length();
							String o = "HTTP/1.0 200 OK\r\n"
									+ "Content-Length: "
									+ len
									+ "\r\n"
									+ "MIME_version:1.0\r\n"
									+ "Content_Type:text/html; charset=utf-8 \r\n\r\n"
									+ outp + "\r\n";
							outstream.println(o);

							outstream.flush();
						}
					} else {

						System.out.println("Loged in" + " requested.");
						String outp = Util.genLogin();

						int len = outp.length();
						String o = "HTTP/1.0 200 OK\r\n"
								+ "Content-Length: "
								+ len
								+ "\r\n"
								+ "MIME_version:1.0\r\n"
								+ "Content_Type:text/html; charset=utf-8 \r\n\r\n"
								+ outp + "\r\n";
						outstream.println(o);

						outstream.flush();
						// outstream.close();

					}

				}

			}

			long m1 = 1;
			while (m1 < 11100000) {
				m1++;
			}
			client.close();
			// /client.close();
		} catch (IOException e) {
			System.out.println("Exception:" + e);
		}
	}

	/**
	 * @param in
	 *            : the request name
	 * @return states numbers: 0 is for succeed login form 1 is for manage form
	 *         other is for login form
	 * 
	 * 
	 */
	private int getState(String in) {
		if (in.indexOf("login?password=" + Entry.password) == 0) {
			return 0;
		}

		if (in.indexOf(Entry.key) == 0) {
			return 1;
		}

		return 2;
	}

	/**
	 * @param in
	 * @return the command need to do (start or kill)
	 */
	private String getCommand(String in) {
		String ret = "";
		int str = in.indexOf(Entry.key + "?Mycommand=");
		if (str == -1)
			return "null";

		str = str + 20 + 11;
		ret = in.substring(str);
		String[] tmp = ret.split("%3A");

		ret = tmp[0] + "###" + tmp[1];
		return ret;
	}

	/**
	 * @param s
	 * @return if it is an GET
	 */
	boolean getrequest(String s) {
		if (s.length() > 0) {
			if (s.substring(0, 3).equalsIgnoreCase("GET"))
				return true;
		}
		return false;
	}

	/**
	 * @param s
	 * @return the request address
	 */
	String getfilename(String s) {
		String f = s.substring(s.indexOf(32) + 1);
		f = f.substring(0, f.indexOf(32));
		try {
			if (f.charAt(0) == '/')
				f = f.substring(1);
		} catch (StringIndexOutOfBoundsException e) {
			System.out.println("Exception:" + e);
		}
		if (f.equals(""))
			f = "index.html";
		return f;
	}

	/**
	 * @param filename
	 * @return if contains the key
	 */
	boolean pass(String filename) {
		return filename.contains(Entry.key);
	}

	/**
	 * 
	 * Send String output to the PrintStream outs;
	 * 
	 * @param outs
	 * @param output
	 */
	void sendString(PrintStream outs, String output) {
		try {

			InputStream is = new ByteArrayInputStream(output.getBytes());
			DataInputStream tmp = new DataInputStream(is);

			int len = output.length();

			byte buf[] = new byte[len];
			tmp.readFully(buf);
			outs.write(buf, 0, len);
			TextIO.putln();
			outs.flush();
			tmp.close();
		} catch (Exception e) {
			System.out.println("Error retrieving file.");
			System.exit(1);
		}
	}
}
